package cn.iocoder.yudao.module.member.vip.service;

import cn.hutool.core.collection.CollUtil;
import cn.iocoder.yudao.framework.business.basic.dao.query.CoreLambdaQueryWrapper;
import cn.iocoder.yudao.framework.business.basic.pojo.vo.UserSimpleVO;
import cn.iocoder.yudao.framework.business.eligibility.service.AppEligibilityBaseService;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.api.member.user.MemberUserApi;
import cn.iocoder.yudao.module.api.member.vip.enums.VipTypeEnum;
import cn.iocoder.yudao.module.api.member.vip.vo.VipUserSummaryVO;
import cn.iocoder.yudao.module.api.member.vip.vo.VipUserVO;
import cn.iocoder.yudao.module.member.vip.dal.dataobject.VipOrderDO;
import cn.iocoder.yudao.module.member.vip.dal.dataobject.VipUserDO;
import cn.iocoder.yudao.module.member.vip.dal.mysql.VipUserMapper;
import cn.iocoder.yudao.module.member.vip.mq.VipProducer;
import jakarta.annotation.Nonnull;
import jakarta.annotation.Nullable;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;

import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;

/**
 * 会员 Service 实现类
 *
 * @author 山野羡民
 */
@Slf4j
@Service
@Validated
public class AppVipUserServiceImpl extends AppEligibilityBaseService<VipUserDO, VipOrderDO, VipUserVO> implements AppVipUserService {
    @Resource
    private VipUserMapper vipUserMapper;

    @Resource
    private MemberUserApi memberUserApi;

    @Resource
    private VipProducer vipProducer;

    @Override
    protected VipUserMapper getInjectedMapper() {
        return vipUserMapper;
    }

    @Nonnull
    @Override
    protected VipUserDO buildForInsert(@Nonnull Long userId) {
        VipUserDO vipUserDO = new VipUserDO();
        vipUserDO.setType(VipTypeEnum.MEMBER.getValue());
        vipUserDO.setBindShopId(0L);
        return vipUserDO;
    }

    @Nonnull
    @Override
    protected VipUserDO buildForUpdate(@Nonnull VipOrderDO order, @Nonnull VipUserDO aDo) {
        VipUserDO vipUserDO = super.buildForUpdate(order, aDo);
        vipUserDO.setType(order.getType());
        if (vipUserDO.getPurchaseCount() == 0 && order.getFromShopId() > 0
            && (vipUserDO.getBindShopId() == null || vipUserDO.getBindShopId() == 0)) {
            // 首次购买会员，未绑定过商家，则绑定来源的店铺
            vipUserDO.setBindShopId(order.getFromShopId());
        }
        return vipUserDO;
    }

    @Override
    public boolean isValid(Long userId, @Nullable VipTypeEnum vipType) {
        try {
            VipUserDO vipUserDO = getOrCreate(userId);
            boolean valid = vipUserDO.isValid();
            if (vipType == null) {
                return valid;
            }
            return valid && Objects.equals(vipType.getValue(), vipUserDO.getType());
        } catch (Exception e) {
            log.error("isValid error", e);
            return false;
        }
    }

    @Override
    public VipUserSummaryVO getVipSummaryByBindShopId(Long shopId) {
        return getInjectedMapper().selectVipSummaryByBindShopId(shopId);
    }

    @Override
    public PageResult<VipUserVO> getPage(Integer current, Integer size, Boolean valid, Long shopId) {
        CoreLambdaQueryWrapper<VipUserDO> wrapper = new CoreLambdaQueryWrapper<>();
        wrapper.eq(VipUserDO::getBindShopId, shopId);
        if (Boolean.TRUE.equals(valid)) {
            wrapper.gt(VipUserDO::getPurchaseCount, 0);
            wrapper.gt(VipUserDO::getExpireTime, LocalDateTime.now());
        } else if (Boolean.FALSE.equals(valid)) {
            wrapper.and(it -> it.eq(VipUserDO::getPurchaseCount, 0)
                    .or().le(VipUserDO::getExpireTime, LocalDateTime.now()));
        }
        PageResult<VipUserVO> page = getPage(current, size, wrapper);
        Map<Long, UserSimpleVO> users = memberUserApi.getUserSimpleMap(convertSet(page.getList(), VipUserVO::getUserId));
        page.getList().forEach(item -> item.setUser(users.getOrDefault(item.getUserId(), UserSimpleVO.ANONYMOUS)));
        return page;
    }

    @Override
    public int vipExpireBySystem() {
        CoreLambdaQueryWrapper<VipUserDO> wrapper = new CoreLambdaQueryWrapper<>();
        wrapper.ne(VipUserDO::getType, VipTypeEnum.NONE.getValue());
        wrapper.le(VipUserDO::getExpireTime, LocalDateTime.now());
        List<VipUserDO> list = getInjectedMapper().selectList(wrapper);
        if (CollUtil.isEmpty(list)) {
            return 0;
        }
        List<VipUserDO> updateList = new ArrayList<>();
        for (VipUserDO vipUserDO : list) {
            vipProducer.sendVipUserExpiredMessage(vipUserDO.getUserId());
            VipUserDO updateObj = new VipUserDO();
            updateObj.setId(vipUserDO.getId());
            updateObj.setType(VipTypeEnum.NONE.getValue());
            updateList.add(updateObj);
        }
        getInjectedMapper().updateById(updateList);
        return updateList.size();
    }

}